<template>
  <AutoHeight>
    <div class="head">
      <filter-common
        ref="filterRef"
        :max-tab="6"
        :label-width="63"
        :can-save-filter="true"
        :is-save-local="true"
        :filter-type="props.tableType"
        :filter-arr="props.filterArr"
        :default-attr="defaultAttr"
        class="filter"
        @updateList="updateList"
      >
        <template #fields="{selectedCondition,filterConditions}">
          <slot name="fields" :selectedCondition="selectedCondition" :filterConditions="filterConditions" />
        </template>
        <template #outerAction>
          <tool-tip content="设置显示字段">
            <el-icon class="tool" @click="setColumns">
              <Tools />
            </el-icon>
          </tool-tip>
          <slot name="outerAction" />
        </template>
      </filter-common>
    </div>
    <el-table :data="props.list" :key="tableKey" :fit="false" v-bind="$attrs" @selection-change="handleSelectionChange" ref="table" class="table-wraper">
      <el-table-column v-if="props.showSelect" type="selection" width="30" :reserve-selection="true" />
      <el-table-column v-if="props.showIndex" type="index" width="60">
        <template #header><slot name="index">序号</slot>
        </template>
      </el-table-column>
      <template v-for="(item) in columnsShow">
        <el-table-column v-if="item.show!==false" :prop="item.key" :key="item.key" :label="item.label" :width="`${item.width}`" :show-overflow-tooltip="true">
          <template #header>
            {{ item.label}}
            <!-- 排序按钮 -->
            <span v-if="item.sortable" class="caret-wrapper" :class="getSortIconClass(item)" @click="()=>handleDefineSortChange(item)"><i class="sort-caret ascending"></i><i class="sort-caret descending"></i></span>
            <slot :name="`head_${item.key}`"></slot>
            <el-icon class="change_width" @mousedown="(e:MouseEvent)=>changeWidth(e,item.key)"><MoreFilled /></el-icon>
          </template>
          <template #default="scope">
            <slot :name="item.key" :row="scope.row">{{ scope.row[item.key]}}</slot>
          </template>
        </el-table-column>
      </template>
    </el-table>
    <ColumnSet v-if="showSetting" @close="closeSetting" @submit="updateSetting" title="设置显示字段" :columns="columnsShow" />
    <div style="overflow-x: auto;">
      <el-row v-if="props.showPagination" :gutter="24" style="margin:10px 0px;min-width:810px;">
        <el-col :span="6">
          <el-dropdown v-if="props.showBatchAction" trigger="click" :hide-on-click="false">
            <el-button type="primary">
              批量操作<el-icon class="el-icon--right"><arrow-down /></el-icon>
            </el-button>
            <template #dropdown>
              <el-dropdown-menu>
                <slot name="defineAction" />
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </el-col>
        <el-col :span="18" :style="{display:'flex',justifyContent:'flex-end'}">
          <el-pagination
            v-model:current-page="currentPage"
            v-model:page-size="pageSize"
            :page-sizes="[20, 40, 60]"
            layout="total, sizes, prev, pager, next, jumper"
            :total="props.total"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
          />
        </el-col>
      </el-row>
    </div>
  </AutoHeight>
</template>

<script lang="ts" setup>
import AutoHeight from '@/components/AutoHeight.vue'
import { onMounted, onUnmounted, computed, ref, reactive } from 'vue'
import { throttle } from 'lodash-es'
import FilterCommon from '@/views/filter/FilterView.vue'
import ToolTip from '@/components/ToolTip.vue'
import ColumnSet from '@/components/ColumnSet.vue'
import { Tools, MoreFilled } from '@element-plus/icons-vue'
import type { Attr, Filter } from '@/views/filter/interface'
import type { List } from '@/views/component/TableView.vue'
export interface Column{
  key: string,
  label: string,
  width: number,
  isArray?: boolean,
  search?: boolean,
  show?: boolean,
  sortable?: boolean
}
interface DefaultSort{
  prop: string,
  order: string | null | undefined
}
interface Props{
  list: any[],
  tableType: string,
  columns: Column[],
  filterArr: Filter[],
  showIndex: boolean,
  showSelect: boolean,
  showPagination: boolean,
  showBatchAction: boolean,
  total: number,
  defaultSort: DefaultSort
}
const props = defineProps<Props>()
// 筛选器
const defaultAttr = computed(() => {
  return ({
    FILTERS: props.columns.reduce((res:Attr[], { key, label, isArray, search }) => {
      if (search !== false) {
        return [...res, { key, label, show: true, isArray: !!isArray }]
      } else {
        return res
      }
    }, [])
  })
})
interface FilterType{
  [key:string]:string | number| (string|number)[]
}
let filterDetail:FilterType = {}
const updateList = (val: FilterType) => {
  filterDetail = val
  $emit('updateList', { ...val, ...orderInfo, pageSize: pageSize.value, currentPage: currentPage.value })
}
// 设置显示字段
const tableKey = ref(1)
let columnsShow = reactive(props.columns)
onMounted(() => {
  const mid = localStorage.getItem(props.tableType)
  if (mid !== null) {
    const storageColumns = JSON.parse(mid)
    updateTableColumns(props.columns, storageColumns)
    columnsShow = reactive(storageColumns)
  } else {
    columnsShow = reactive(props.columns.map(({ key, label, width, sortable }) => ({ key, label, width, sortable, show: true })))
  }
})
// 本地存储的表格显示字段与最新的同步
const updateTableColumns = (newColumns: Column[], storageColumns: Column[]) => {
  newColumns.forEach((item: Column) => {
    const sub = storageColumns.find(sub => sub.key === item.key)
    if (sub) {
      // 同步信息
      const { label, sortable } = item
      sub.label = label
      sub.sortable = sortable
    } else {
      // 增加显示字段
      storageColumns.push({ ...item, show: true })
    }
  })
  // 删除废弃字段
  storageColumns.forEach((item:Column, index:number, arr:Column[]) => {
    if (!newColumns.some(sub => sub.key === item.key)) {
      arr.splice(index, 1)
    }
  })
}
const showSetting = ref(false)
const setColumns = () => {
  showSetting.value = true
}
const closeSetting = () => {
  showSetting.value = false
}
const updateSetting = (data: Column[]) => {
  columnsShow = reactive(data)
  tableKey.value = Math.random()
  localStorage.setItem(props.tableType, JSON.stringify(data))
}
// 改变宽度
let beginWidth: number = 0
let movedKey: string = ''
onMounted(() => {
  document.addEventListener('mousemove', throttle(handleMove, 30))
  document.addEventListener('mouseup', saveResult)
})
onUnmounted(() => {
  document.removeEventListener('mousemove', handleMove)
  document.removeEventListener('mouseup', saveResult)
})
const saveResult = () => {
  if (movedKey) {
    movedKey = ''
    localStorage.setItem(props.tableType, JSON.stringify(columnsShow))
  }
}
const changeWidth = (e: MouseEvent, key: string) => {
  beginWidth = e.clientX
  movedKey = key
}
const handleMove = (e: MouseEvent) => {
  if (!movedKey) { return }
  const moveDis = e.clientX - beginWidth
  columnsShow.forEach(item => {
    if (item.key === movedKey) {
      const mid = item.width + moveDis
      item.width = mid > 80 ? mid : 80
      beginWidth = e.clientX
    }
  })
}
// 选中行
const $emit = defineEmits(['changeSelect', 'updateList'])
const handleSelectionChange = (val: List[]) => {
  $emit('changeSelect', val)
}
// 排序
const orderInfo: DefaultSort = reactive(props.defaultSort || {})
const sortOrder: string[] = ['ascending', 'descending']
const handleDefineSortChange = (column: Column) => {
  const index = sortOrder.findIndex(item => item === orderInfo.order)
  let nextIndex:number = 0
  if (orderInfo.prop === column.key) {
    nextIndex = index < (sortOrder.length - 1) ? index + 1 : 0
  }
  orderInfo.prop = column.key
  orderInfo.order = sortOrder[nextIndex]
  currentPage.value = 1
  $emit('updateList', { ...filterDetail, ...orderInfo, pageSize: pageSize.value, currentPage: currentPage.value })
}
const getSortIconClass = (column: Column) => {
  if (orderInfo.prop !== column.key) {
    return ''
  } else {
    return orderInfo.order
  }
}
// 分页
const currentPage = ref(1)
const pageSize = ref(20)
const handleSizeChange = () => {
  currentPage.value = 1
  handleCurrentChange()
}
const handleCurrentChange = () => {
  $emit('updateList', { ...filterDetail, ...orderInfo, pageSize: pageSize.value, currentPage: currentPage.value })
}
const previousPage = (len: number) => {
  const num = Math.ceil(len / pageSize.value)
  currentPage.value = currentPage.value - num > 1 ? currentPage.value - num : 1
  handleCurrentChange()
}
// 清除选中
const table = ref()
const clearSelect = () => {
  table.value.clearSelection()
}
const filterRef = ref()
const setFilterField = (key: string, value: any) => {
  filterRef.value.setFieldValue(key, value)
}
const handleSearch = () => {
  filterRef.value.handleSearch()
}
// 暴露方法供父组件调用
defineExpose({
  previousPage,
  clearSelect,
  setFilterField,
  handleSearch
})

</script>
<style lang="less" scoped>
.head{
  display: flex;
  flex-shrink: 0;
  .filter{
    flex:1;
  }
  .tool{
    margin-right: 10px;
  }
}
thead>tr>th>div.cell{
  position: relative;
}
.change_width{
  transform:rotate(90deg);
  position: absolute;
  right:0;
  top:12px;
  cursor:ew-resize;
}
.table-wraper{
  flex:1;
  overflow: auto;
  width:100%;
}
::v-deep(.el-form-item__content){
  width:200px;
}
::v-deep(.el-form-item){
  margin-bottom: 10px!important;
}

</style>
